package com.pdg.android.splorr.data;

import com.pdg.android.splorr.R;
import com.pdg.android.splorr.Utilities;
import com.pdg.android.splorr.data.enums.CloseDoorActionResult;
import com.pdg.android.splorr.data.enums.DoorState;
import com.pdg.android.splorr.data.enums.DropItemActionResult;
import com.pdg.android.splorr.data.enums.GameState;
import com.pdg.android.splorr.data.enums.MoveAheadResult;
import com.pdg.android.splorr.data.enums.OpenDoorActionResult;
import com.pdg.android.splorr.data.enums.RoomDirection;
import com.pdg.android.splorr.data.enums.SearchForItemsResult;
import com.pdg.android.splorr.data.enums.SearchWallActionResult;
import com.pdg.android.splorr.data.enums.TakeItemActionResult;
import com.pdg.android.splorr.data.enums.UnlockDoorActionResult;

import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import com.pdg.android.common.GameDataBase;

public class Game extends GameDataBase<GameState>{

	//keys
	private static final String KEY_GAME_IN_PROGRESS = "game_in_progress";
	private static final String KEY_CURRENT_ROOM_SUMMARY = "current_room_summary";
	private static final String KEY_LAST_ACTION_RESULT_TEXT = "last_action_result_text";
	private static final String KEY_CURRENT_EQUIPMENT_SUMMARY = "current_equipment_summary";
	//defaults
	private static final boolean DEFAULT_GAME_IN_PROGRESS = false;
	private static final String DEFAULT_CURRENT_ROOM_SUMMARY = "";
	private static final String DEFAULT_LAST_ACTION_RESULT_TEXT = "";
	private static final String DEFAULT_CURRENT_EQUIPMENT_SUMMARY = "";
	//fields
	private boolean gameInProgress;
	private String currentRoomSummary;
	private Player playerData;
	private Maze mazeData;
	private Utilities utilities;
	private String lastActionResultText = DEFAULT_LAST_ACTION_RESULT_TEXT;
	private String currentEquipmentSummary = DEFAULT_CURRENT_EQUIPMENT_SUMMARY;

	@Override
	protected void onLoad(SharedPreferences thePreferences) {
		setGameInProgress(thePreferences.getBoolean(KEY_GAME_IN_PROGRESS, DEFAULT_GAME_IN_PROGRESS));
		setCurrentRoomSummary(thePreferences.getString(KEY_CURRENT_ROOM_SUMMARY, DEFAULT_CURRENT_ROOM_SUMMARY));
		setCurrentEquipmentSummary(thePreferences.getString(KEY_CURRENT_EQUIPMENT_SUMMARY, DEFAULT_CURRENT_EQUIPMENT_SUMMARY));
		setLastActionResultText(thePreferences.getString(KEY_LAST_ACTION_RESULT_TEXT, DEFAULT_LAST_ACTION_RESULT_TEXT));
		getPlayerData().load(thePreferences);
		getMazeData().load(thePreferences);
	}


	private void setCurrentEquipmentSummary(String theCurrentEquipmentSummary) {
		currentEquipmentSummary = theCurrentEquipmentSummary;
	}


	@Override
	protected void onCommit(Editor theEditor) {
		theEditor.putBoolean(KEY_GAME_IN_PROGRESS, isGameInProgress());
		theEditor.putString(KEY_CURRENT_ROOM_SUMMARY, getCurrentRoomSummary());
		theEditor.putString(KEY_CURRENT_EQUIPMENT_SUMMARY, getCurrentEquipmentSummary());
		theEditor.putString(KEY_LAST_ACTION_RESULT_TEXT, getLastActionResultText());
		getPlayerData().commit(theEditor);
		getMazeData().commit(theEditor);
	}
	
	public Game(){
		setUtilities(new Utilities(this));
		setPlayerData(new Player(this));
		setMazeData(new Maze(this));
	}

	private void setMazeData(Maze theMazeData) {
		mazeData = theMazeData;
	}
	
	public Maze getMazeData(){
		return mazeData;
	}


	private void setPlayerData(Player thePlayerData) {
		playerData = thePlayerData;
	}
	
	public Player getPlayerData(){
		return playerData;
	}


	@Override
	protected GameState getDefaultCurrentState() {
		return GameState.MAIN_MENU;
	}

	@Override
	protected GameState decodeCurrentState(String theValue) {
		return GameState.valueOf(theValue);
	}

	@Override
	protected String encodeCurrentState(GameState theValue) {
		return theValue.name();
	}

	private void setGameInProgress(boolean theGameInProgress) {
		gameInProgress = theGameInProgress;
	}
	public boolean isGameInProgress() {
		return gameInProgress;
	}


	public void newGame(int theSize) {
		int theWidth = getContext().getResources().getIntArray(R.array.maze_size_widths)[theSize];
		int theHeight = getContext().getResources().getIntArray(R.array.maze_size_heights)[theSize];
		getMazeData().newGame(theWidth,theHeight);
		getPlayerData().newGame();
		setGameInProgress(true);
		setLastActionResultText(getContext().getResources().getString(R.string.game_start_action_result));
		updateSummaries();
	}


	private void updateSummaries() {
		updateCurrentRoomSummary();
		updateCurrentEquipmentSummary();
	}


	private void updateCurrentEquipmentSummary() {
		String theSummary = getLastActionResultText();
		theSummary += getContext().getString(R.string.inventory_items_in_possesion_line);
		setCurrentEquipmentSummary(theSummary);
	}


	private void updateCurrentRoomSummary() {
		Player thePlayer = getPlayerData();
		Room theRoom = getMazeData().getRoom(thePlayer.getX(),thePlayer.getY());
		Door theDoor;
		DoorState theTransition;
		String theSummary = getLastActionResultText();
		
		RoomDirection ahead = thePlayer.getFacing();
		theDoor = theRoom.getDoor(ahead);
		theTransition = theDoor.getDoorState();
		theSummary += String.format(getContext().getString(R.string.summary_ahead_format),getContext().getResources().getStringArray(theTransition.getStringArrayId())[theTransition.getArrayIndex()]);
		
		if(theDoor.hasWallMark()){
			theSummary += String.format(getContext().getString(R.string.summary_wall_mark_format), theDoor.getWallMark());
		}
		
		RoomDirection right = ahead.next();
		theDoor = theRoom.getDoor(right);
		theTransition = theDoor.getDoorState();
		theSummary += String.format(getContext().getString(R.string.summary_right_format),getContext().getResources().getStringArray(theTransition.getStringArrayId())[theTransition.getArrayIndex()]);
		
		RoomDirection behind = ahead.opposite();
		theDoor = theRoom.getDoor(behind);
		theTransition = theDoor.getDoorState();
		theSummary += String.format(getContext().getString(R.string.summary_behind_format),getContext().getResources().getStringArray(theTransition.getStringArrayId())[theTransition.getArrayIndex()]);
		
		RoomDirection left = ahead.previous();
		theDoor = theRoom.getDoor(left);
		theTransition = theDoor.getDoorState();
		theSummary += String.format(getContext().getString(R.string.summary_left_format),getContext().getResources().getStringArray(theTransition.getStringArrayId())[theTransition.getArrayIndex()]);
		
		switch(theRoom.getRoomState()){
		case ENTRANCE:
			theSummary += getContext().getString(R.string.summary_entrance);
			break;
		case EXIT:
			theSummary += getContext().getString(R.string.summary_exit);
			break;
		default:
			break;
		}

		if(theRoom.getVisibleItemCount()>0){
			theSummary += String.format(getContext().getString(R.string.room_items_title),theRoom.getVisibleItemCount());
		}
		
		
		setCurrentRoomSummary(theSummary);
	}


	private String getLastActionResultText() {
		return lastActionResultText;
	}
	
	private void setLastActionResultText(String theLastActionResultText){
		lastActionResultText = theLastActionResultText;
	}


	public GameState getGameStateForPlayerState() {
		return getPlayerData().getGameStateForPlayerState();
	}


	public String getCurrentRoomSummary() {
		return currentRoomSummary;
	}


	public void setCurrentRoomSummary(String currentRoomSummary) {
		this.currentRoomSummary = currentRoomSummary;
	}


	public boolean turnAround() {
		boolean theResult = getPlayerData().turnAround();
		setLastActionResultText(getContext().getString(R.string.move_action_result_turn_around_success));
		updateSummaries();
		return theResult;
	}


	public boolean turnRight() {
		boolean theResult = getPlayerData().turnRight();
		setLastActionResultText(getContext().getString(R.string.move_action_result_turn_right_success));
		updateSummaries();
		return theResult;
	}


	public boolean moveAhead() {
		MoveAheadResult theResult = getPlayerData().moveAhead();
		setLastActionResultText(getContext().getString(theResult.getStringId()));
		updateSummaries();
		return theResult.isSuccess();
	}


	public boolean turnLeft() {
		boolean theResult = getPlayerData().turnLeft();
		setLastActionResultText(getContext().getString(R.string.move_action_result_turn_left_success));
		updateSummaries();
		return theResult;
	}


	public Utilities getUtilities() {
		return utilities;
	}


	private void setUtilities(Utilities utilities) {
		this.utilities = utilities;
	}


	public Room getCurrentRoom() {
		return this.getMazeData().getRoom(getPlayerData().getX(), getPlayerData().getY());
	}


	public boolean closeDoor() {
		CloseDoorActionResult theResult = getPlayerData().closeDoor();
		setLastActionResultText(getContext().getString(theResult.getStringId()));
		updateSummaries();
		return theResult.isSuccess();
	}


	public boolean openDoor() {
		OpenDoorActionResult theResult = getPlayerData().openDoor();
		setLastActionResultText(getContext().getString(theResult.getStringId()));
		updateSummaries();
		return theResult.isSuccess();
	}


	public boolean takeItem(int itemIndex) {
		Room theRoom = getPlayerData().getCurrentRoom();
		RoomItem theItem = theRoom.getRoomItem(itemIndex);
		TakeItemActionResult theResult = getPlayerData().takeItem(itemIndex);
		String theLastActionResultText = getContext().getString(theResult.getStringId());
		if(theResult.isFormatString()){
			theLastActionResultText = String.format(theLastActionResultText,theItem.getName());
		}
		setLastActionResultText(theLastActionResultText);
		updateSummaries();
		return theResult.isSuccess();
	}


	public void setWallMark(String theWallMark) {
		getPlayerData().setWallMark(theWallMark);
		setLastActionResultText(getContext().getString(R.string.mark_wall_action_result_success));
		updateSummaries();
	}


	public void examineLock() {
		Room theRoom = getPlayerData().getCurrentRoom();
		Door theDoor = theRoom.getDoor(getPlayerData().getFacing());
		setLastActionResultText(String.format(getContext().getString(R.string.examine_lock_format),theDoor.getLockName()));
		updateSummaries();
	}


	public boolean unlockDoor() {
		UnlockDoorActionResult theResult = getPlayerData().unlockDoor();
		setLastActionResultText(getContext().getString(theResult.getStringId()));
		updateSummaries();
		return theResult.isSuccess();
		
	}


	public String getCurrentEquipmentSummary() {
		return currentEquipmentSummary ;
	}


	public boolean searchWall() {
		SearchWallActionResult theResult = getPlayerData().searchWall();
		setLastActionResultText(getContext().getString(theResult.getStringId()));
		updateSummaries();
		return theResult.isSuccess();
	}


	public boolean dropItem(int theItemIndex) {
		DropItemActionResult theResult = getPlayerData().dropItem(theItemIndex);
		setLastActionResultText(getContext().getString(theResult.getStringId()));
		updateSummaries();
		return theResult.isSuccess();
		
	}


	public boolean searchForItems() {
		SearchForItemsResult theResult = getPlayerData().searchForItems();
		setLastActionResultText(getContext().getString(theResult.getStringId()));
		updateSummaries();
		return theResult.isSuccess();
	}


}
